package personnel.department.pages;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.TableColumn;

import personnel.department.dao.QueryBuilder;
import personnel.department.dao.entity.Employee;
import personnel.department.dao.entity.UniqueObject;
import personnel.department.pages.addpage.AddPersonalPage;
import personnel.department.pages.constants.Icons;
import personnel.department.utils.ExportUtils;
import personnel.department.utils.ReflectionUtils;
import personnel.department.utils.TranslatorUtils;

//TODO refactor me
public abstract class AbstractPage<T extends UniqueObject> {

	private CTabFolder tabFolder;
	private String pageName;
	private PagesLogic pagesLogic;
	private TableViewer viewer;
	private TwoColumnFieldsComposite searchParamComposite;
	private AbstractPage<T> currentPage;
	private Map<Field, Object> widgetValueByField;
	protected PDTable<T> table;
	protected Label quantityRows;

	public AbstractPage(String pageName) {
		pagesLogic = PagesLogic.getInstance();
		this.tabFolder = pagesLogic.getTabFolder();
		this.pageName = pageName;
		currentPage = this;
	}

	public Class<T> getEntityClass() {
		return ReflectionUtils.getGenericParameterClass(this.getClass(), AbstractPage.class, 0);
	}

	public void create() {
		if (isPageExist()) {
			return;
		}
		
		CTabItem tabItem = createTabItem();

		Composite parent = createParentComposite();

		createSeachContent(parent);

		createButtonComposite(parent);

		createTable(parent);

		tabItem.setControl(parent);
		tabFolder.setSelection(tabItem);

	}

	protected CTabItem createTabItem() {
		CTabItem tabItem = PagesLogic.getInstance().createTabItem(pageName);
		return tabItem;
	}

	private boolean isPageExist() {
		for (CTabItem item : tabFolder.getItems()) {
			if (item.getText().equals(pageName)) {
				tabFolder.setSelection(item);
				return true;
			}
		}
		return false;
	}

	protected void createButtonComposite(Composite parent) {
		Composite c = new Composite(parent, SWT.NONE);
		c.setLayout(new GridLayout(2, false));
		c.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create());
		
		Button findButton = new Button(c, SWT.PUSH);
		findButton.setImage(new Image(findButton.getDisplay(), Icons.SEARCH_ICON.getPath()));
		findButton.setText("Поиск");
		findButton.addListener(SWT.Selection, new Listener() {
			
			@Override
			public void handleEvent(Event e) {
				QueryBuilder queryBuilder = new QueryBuilder(searchParamComposite.getWidgetValueByField());
				List<Employee> result = queryBuilder.execute();
				table.clear();
				table.addElements((List<T>) result);
				quantityRows.setText("Количество записей: " + String.valueOf(result.size()));
				quantityRows.pack();
				pagesLogic.getResultComposite().updateInfo(result);
			}
		});
		
		Button export = new Button(c, SWT.PUSH);
		export.setImage(new Image(export.getDisplay(), Icons.EXPORT_ICON.getPath()));
		export.setText("Экспорт в CSV");
		export.addListener(SWT.Selection, new Listener() {
			
			@Override
			public void handleEvent(Event event) {
		        FileDialog fd = new FileDialog(PagesLogic.getInstance().getMainShell(), SWT.SAVE);
		        fd.setText("Сохранить");
		        fd.setFilterPath("C:/");
		        String[] filterExt = { "*.csv"};
		        fd.setFilterExtensions(filterExt);
		        String fileName = fd.open();
		        String dataToCsv = table.getDataToCsv();
		        try {
					ExportUtils.toCSV(fileName, dataToCsv);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}

	protected void createTable(Composite parent) {
		Composite c = new Composite(parent, SWT.NONE);
		GridDataFactory.fillDefaults().grab(true, true).applyTo(c);
		c.setLayout(new GridLayout());
		
		quantityRows = new Label(c, SWT.NONE);
		quantityRows.setText("Количество записей");
		
		table = new PDTable<T>(c) {
			@Override
			public List<T> setModelProvider() {
				return currentPage.getModelProvider();
			}
			
			@Override
			protected void createColumns(Composite parent, TableViewer viewer) {
				currentPage.createColumns(parent, viewer);
			}
			
			
		};
		
		viewer = table.getViewer();
		table.createTable();
		table.setOpenAction();
		table.setSelectionAction(event -> {
			IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
			Employee employee = (Employee) selection.getFirstElement();
			pagesLogic.getInfoComposite().updateInfo(employee);
		});
		
		pagesLogic.setSearchTable((PDTable<UniqueObject>) table);
	}

	protected abstract List<T> getModelProvider();

	protected abstract void createColumns(Composite parent, TableViewer viewer);

	protected void createSeachContent(final Composite parent) {
		List<Field> searchFields = getSearchFields();
		final ScrolledComposite sc = createScrolledComposite(parent);
		searchParamComposite = new TwoColumnFieldsComposite(sc, searchFields, SWT.BORDER, true);
		searchParamComposite.createControl();
		widgetValueByField = searchParamComposite.getWidgetValueByField();
		settingScrolled(sc, searchParamComposite);
	}

	protected void settingScrolled(final ScrolledComposite sc, Composite composite) {
		sc.setContent(composite);
		
		sc.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		sc.addListener(SWT.Activate, event -> sc.setFocus());
	}

	protected ScrolledComposite createScrolledComposite(final Composite parent) {
		final ScrolledComposite sc = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.NONE);
		sc.setExpandHorizontal(true);
		sc.setExpandVertical(true);
		sc.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).hint(SWT.DEFAULT, 250).create());
		return sc;
	}

	private List<Field> getSearchFields() {
		Field[] fields = getEntityClass().getDeclaredFields();
		List<Field> searchFields = TranslatorUtils.getTranslatorFields(fields);
		return searchFields;
	}

	protected Composite createParentComposite() {
		return createComposite(tabFolder, 1, false);
	}

	private Composite createComposite(Composite parent, int numColumns, boolean equalColumn) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new GridLayout(numColumns, equalColumn));
//		composite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
		return composite;
	}

	protected TableViewerColumn createTableViewerColumn(String title, int bound, final int colNumber) {
		final TableViewerColumn viewerColumn = new TableViewerColumn(viewer,
				SWT.NONE);
		final TableColumn column = viewerColumn.getColumn();
		column.setText(title);
		column.setWidth(bound);
		column.setResizable(true);
		column.setMoveable(true);
		return viewerColumn;
	}
}
